package com.epalmpay.service.activity.impl;

import java.util.*;

import javax.annotation.Resource;

import com.epalmpay.exception.ApplicationException;
import com.epalmpay.payplat.result.PayResult;
import com.epalmpay.service.weixin.impl.WalletServiceImpl;
import com.epalmpay.status.Rescode;
import com.epalmpay.entity.*;
import com.epalmpay.enumdef.ActivityEnum;
import com.epalmpay.enumdef.BizEnum;
import com.epalmpay.enumdef.CommonEnum;
import com.epalmpay.mapper.*;
import com.epalmpay.service.weixin.IWalletService;
import com.epalmpay.util.*;
import com.epalmpay.util.payplat.UtilFun;
import org.slf4j.*;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Service;

import com.epalmpay.dto.activity.RedPackageDetailOutDTO;
import com.epalmpay.dto.activity.RedPackageInDTO;
import com.epalmpay.dto.activity.RedPackageListOutDTO;
import com.epalmpay.dto.activity.RedPackageOutDTO;
import com.epalmpay.dto.activity.RedpackageAddInDTO;
import com.epalmpay.enumdef.ActivityEnum.CouponValidType;
import com.epalmpay.enumdef.ActivityEnum.RedPackageStatus;
import com.epalmpay.enumdef.ActivityEnum.RedPackageType;
import com.epalmpay.service.activity.IActivityRedPackageService;
import com.epalmpay.service.groupaccount.IGroupAccountService;

import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;


@Service("activityRedPackageService") 
public class ActivityRedPackageServiceImpl implements IActivityRedPackageService {
	@Resource
	private IWalletService walletService;
	@Resource  
    private RedpackageMapper redpackageMapper;
	@Resource  
    private ActivityBaseMapper activityBaseMapper;
	@Resource  
    private RedpackageUserMapper redpackageUserMapper;
	@Resource
	private GroupAccountMapper groupAccountMapper;
	@Resource
	private GroupAccountLogMapper groupAccountLogMapper;
	@Resource
    private MemberMapper memberMapper;
	@Resource
    private GroupMapper groupMapper;
	@Resource
	private TradeOfflineMapper tradeOfflineMapper;

	@Resource
	private IGroupAccountService groupAccountService;
	@Resource(name="transactionManager")
	private DataSourceTransactionManager transactionManager;


	private static org.slf4j.Logger logger = LoggerFactory.getLogger(ActivityRedPackageServiceImpl.class);


	public List<RedPackageOutDTO> getRedPackageList(RedPackageInDTO redPackageInDTO,Page page) throws Exception{
		
		Map<String,Object> param=new HashMap<String,Object>();
		param.put("groupID", redPackageInDTO.getGroupId());
		param.put("purposeType", redPackageInDTO.getPurposeType());
		param.put("redPackageStatus", redPackageInDTO.getRedPackageStatus());
		param.put("name", redPackageInDTO.getName());
		param.put("getType", redPackageInDTO.getGetType());
		
		List<RedPackageOutDTO> result = new ArrayList<RedPackageOutDTO>();

		int sumCount = redpackageMapper.selectRedpackageListCount(param);
		page.setTotalResult(sumCount);
		if(sumCount<=0)
			return null;
		
		param.put("limit", page.getShowCount());
		param.put("start", page.getShowCount()*(page.getCurrentPage()-1));
		
		List<Redpackage> redpackageList = redpackageMapper.selectRedpackageList(param);
		
		for (Redpackage redpackage : redpackageList) {
			RedPackageOutDTO redPackageOutDTO = new RedPackageOutDTO();			
			PropertyCopyUtil.copyPropertiesExclude(redpackage,redPackageOutDTO);
			result.add(redPackageOutDTO);
		}
		
		return result;
	}

	public RedPackageListOutDTO getRedPackageList(RedPackageInDTO redPackageInDTO) throws Exception{
		RedPackageListOutDTO result = new RedPackageListOutDTO();

		Map<String,Object> param=new HashMap<String,Object>();
		param.put("groupID", redPackageInDTO.getGroupId());
		param.put("purposeType", redPackageInDTO.getPurposeType());
		param.put("redPackageStatus", redPackageInDTO.getRedPackageStatus());
		param.put("name", redPackageInDTO.getName());
		param.put("getType", redPackageInDTO.getGetType());

		int sumCount = redpackageMapper.selectRedpackageListCount(param);
		result.setSumCount(sumCount);
		if(sumCount<=0)
			return result;

		param.put("limit", redPackageInDTO.getPageSize());
		param.put("start", redPackageInDTO.getPageSize()*(redPackageInDTO.getPageNo()-1));

		List<Redpackage> redpackageList = redpackageMapper.selectRedpackageList(param);
		List<RedPackageOutDTO> redPackageOutDTOList = new ArrayList<RedPackageOutDTO>();
		for (Redpackage redpackage : redpackageList) {
			RedPackageOutDTO redPackageOutDTO = new RedPackageOutDTO();
			PropertyCopyUtil.copyPropertiesExclude(redpackage,redPackageOutDTO);
			redPackageOutDTOList.add(redPackageOutDTO);
		}
		if(redPackageOutDTOList.size()>0)
			result.setRedPackageOutDTOList(redPackageOutDTOList);

		return result;
	}



	public List<RedPackageOutDTO> GetSpecialRedpackageList(RedPackageInDTO redPackageInDTO) throws Exception{

		Map<String,Object> param=new HashMap<String,Object>();
		param.put("groupID", redPackageInDTO.getGroupId());
		param.put("purposeType", redPackageInDTO.getPurposeType());


		List<RedPackageOutDTO> result = new ArrayList<RedPackageOutDTO>();

		int sumCount = redpackageMapper.selectRedpackageListCount(param);

		if(sumCount<=0)
			return null;



		List<Redpackage> redpackageList = redpackageMapper.GetSpecialActivityRedpackageList(param);

		for (Redpackage redpackage : redpackageList) {
			RedPackageOutDTO redPackageOutDTO = new RedPackageOutDTO();
			PropertyCopyUtil.copyPropertiesExclude(redpackage,redPackageOutDTO);
			result.add(redPackageOutDTO);
		}

		return result;
	}
	
	public RedPackageListOutDTO  getToIndexData(RedPackageInDTO redPackageInDTO) throws Exception{
		RedPackageListOutDTO result = new RedPackageListOutDTO();    	
        Map<String,Object> param=new HashMap<String,Object>();
        param.put("groupId", redPackageInDTO.getGroupId());
        
        Map<String,Object> selectResultMap = redpackageMapper.getIndexData(param);
        result.setRoutineNum((Integer.parseInt(selectResultMap.get("routine_num").toString())));
        if(selectResultMap.get("routine_amount")!=null)
        	result.setRoutineAmount((Integer.parseInt(selectResultMap.get("routine_amount").toString())));
        result.setUnroutineNum((Integer.parseInt(selectResultMap.get("unroutine_num").toString())));
        if(selectResultMap.get("unroutine_amount")!=null)
        	result.setUnroutineAmount((Integer.parseInt(selectResultMap.get("unroutine_amount").toString())));
        result.setMemberNum((Integer.parseInt(selectResultMap.get("member_num").toString())));
        if(selectResultMap.get("member_amount")!=null)
        	result.setMemberAmount((Integer.parseInt(selectResultMap.get("member_amount").toString())));

		return result;
	}
	
	public int  saveRedpackage(RedpackageAddInDTO redpackageAddInDTO,String url) throws Exception{
    	int result = 0;
		//总预算金额
		Integer sumAmount = 0;
        Boolean autoAddFlag = Boolean.FALSE;

    	Redpackage record = new Redpackage();
    	if(redpackageAddInDTO.getValidTimeType() == CouponValidType.FixedTime.getType()){
    		redpackageAddInDTO.setAftergetValidtime(null);
    	}
    	else if (redpackageAddInDTO.getValidTimeType() == CouponValidType.ValidAfterGet.getType()){
    		redpackageAddInDTO.setEndGetTime(null);
    	}

    	if(redpackageAddInDTO.getRedpackageType() == RedPackageType.FixedAmount.getType()){//固定金额
    		redpackageAddInDTO.setMaxValue(null);
			redpackageAddInDTO.setMinValue(null);
			if(redpackageAddInDTO.getTotalCount()==null||redpackageAddInDTO.getTotalCount()==0) {
				sumAmount = Const.REDPACKAGE_FREEZE_AMOUNT;
				autoAddFlag = Boolean.TRUE;
			}else{
				sumAmount = redpackageAddInDTO.getTotalCount()*redpackageAddInDTO.getFaceValue();
			}
    	}
    	else if(redpackageAddInDTO.getRedpackageType() == RedPackageType.RandomAmount.getType()){//随机金额
    		redpackageAddInDTO.setFaceValue(null);
			if(redpackageAddInDTO.getSumAmount()==null||redpackageAddInDTO.getSumAmount()==0) {
				sumAmount = Const.REDPACKAGE_FREEZE_AMOUNT;
				autoAddFlag = Boolean.TRUE;
			}else{
				sumAmount = redpackageAddInDTO.getSumAmount();
			}
		}
		//设置红包总预算
		redpackageAddInDTO.setSumAmount(sumAmount);

    	//生成分享链接或二维码连接
    	//if(redpackageAddInDTO.getIsGetUrl()){}
    	//if(redpackageAddInDTO.getIsGetCrcodeUrl()){}
    	
    	PropertyCopyUtil.copyPropertiesExclude(redpackageAddInDTO,record);
    	record.setGmtCreate(new Date());
    	record.setGmtModified(new Date());
    	record.setStatus(RedPackageStatus.WaitingForGet.getType());//待领取
    	record.setCreator(redpackageAddInDTO.getLoginId());
    	record.setAutoAddFlag(autoAddFlag);
    	
    	result = redpackageMapper.insert(record);

    	//临时解决 不是会员的有点问题
		if(redpackageAddInDTO.getGetType()==4){
			Redpackage redpackage = new Redpackage();
			redpackage.setId(record.getId());
			if(redpackageAddInDTO.getIsGetUrl()!=null&&redpackageAddInDTO.getIsGetUrl().equals(true)){//生成领取链接
				redpackage.setGmtModified(new Date());
				//	String linkUrl="http://sbs-test.eboss007.com/2/coupon_full_detail.html?id="+record.getId();
				String linkUrl=url+"/api/oAuth2/getDiscount?id="+record.getId()+"&"+"groupId="+redpackageAddInDTO.getGroupId()+"&type=2";
				redpackage.setGetUrl(linkUrl);
			}

			if(redpackageAddInDTO.getIsGetCrcodeUrl()!=null&&redpackageAddInDTO.getIsGetCrcodeUrl().equals(true)){//生成二维码
				String qrcodeUrl=url+"/api/oAuth2/getDiscount?id="+record.getId()+"&"+"groupId="+redpackageAddInDTO.getGroupId()+"&type=2";;
				redpackage.setGetCrcodeUrl(qrcodeUrl);
			}
			if(redpackageAddInDTO.getIsGetUrl()!=null || redpackageAddInDTO.getIsGetCrcodeUrl()!=null){

				redpackageMapper.updateByPrimaryKeySelective(redpackage);
			}
		}

		//增加营销账户冻结金额
		groupAccountService.updateAmount(redpackageAddInDTO.getGroupId(),
				BizEnum.SaleAccountSubjectType.RedPackageCreate,sumAmount,record.getId(),null,null);

    	return result;
	}
	
	public RedPackageDetailOutDTO  getRedpackageDetail(RedPackageInDTO inDTO,Page page) throws Exception{
		RedPackageDetailOutDTO result = new RedPackageDetailOutDTO();
    	
		Redpackage redpackage =  redpackageMapper.selectRedpackageDetailById(inDTO.getId());
		if(redpackage.getGetCrcodeUrl() !=null){
			String st_fname=redpackage.getGetCrcodeUrl().replaceAll("&","%26");
			redpackage.setGetCrcodeUrl(st_fname);
		}
    	
		result.setRedpackage(redpackage);
    	
    	//取得关联活动名称
    	Map<String,Object> param=new HashMap<String,Object>();
        param.put("redpackageId", inDTO.getId());
        result.setActivityBaseList(activityBaseMapper.selectActiityByRedpackageId(param));
    	
        //取得优惠券使用记录
        param.clear();
        param.put("redpackageId", inDTO.getId());
        param.put("getStatus", inDTO.getGetStatus());
        param.put("startDate", inDTO.getStartDate());
        param.put("endDate", inDTO.getEndDate());
        param.put("name", inDTO.getName());
        
		int sumCount = redpackageUserMapper.selectRedpackageUserListCount(param);
		page.setTotalResult(sumCount);
		if(sumCount>0){
			param.put("limit", page.getShowCount());
			param.put("start", page.getShowCount()*(page.getCurrentPage()-1));
			result.setRedpackageUserDTOList(redpackageUserMapper.selectRedpackageUserList(param));
		}		

    	return result;
		
	}

	@Override
	public List<Map> getRedpackageListById(Set<Long> redpackageIdSet) {
		return redpackageMapper.getRedpackageListById(redpackageIdSet);
	}

	//准备去发红包
	@Override
	public List<Redpackage> redPackageList(Redpackage redpackage) throws Exception {
//		redpackage.setTodayTime(new Date());
//		redpackage.setValidTimeType(ActivityEnum.CouponValidType.ValidAfterGet.getType());
		redpackage.setStatus(ActivityEnum.RedPackageStatus.WaitingForGet.getType());
		return redpackageMapper.redPackageList(redpackage);
	}




	/**
	 * 根据id 去查询红包的数量
	 */
	@Override
	public Redpackage findById(RedPackageInDTO redPackageInDTO) {
		
		return redpackageMapper.findById(redPackageInDTO.getRedpackageId());
	}


	//更新红包数量
	@Override
	public void updateRedPackage(Redpackage redpackage) {
		redpackageMapper.updateByPrimaryKeySelective(redpackage);
		
	}


	public int endRedpackage(Long redpackageId) throws Exception{
		DefaultTransactionDefinition def = new DefaultTransactionDefinition();
		def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW); // 事物隔离级别，开启新事务
		TransactionStatus status = transactionManager.getTransaction(def); // 获得事务状态

		int result =0;

		try {
			Redpackage record = new Redpackage();
			record.setId(redpackageId);
			record.setGmtModified(new Date());
			record.setEndGetTime(new Date());
			record.setStatus(RedPackageStatus.Over.getType());
			redpackageMapper.updateByPrimaryKeySelective(record);
			//获取更新后的记录
			record = redpackageMapper.selectByPrimaryKey(redpackageId);

			//计算解冻金额
			Integer unfreezeAmount = (record.getSumAmount() == null ? 0 : record.getSumAmount()) -
					(record.getUsedAmount() == null ? 0 : record.getUsedAmount());
			if (unfreezeAmount > 0) {
				//解冻营销账户冻结金额
				groupAccountService.updateAmount(record.getGroupId(),
						BizEnum.SaleAccountSubjectType.RedPackageUnfreeze, unfreezeAmount, record.getId(), null, null);
			}
			transactionManager.commit(status);
		}catch (Exception e) {
			transactionManager.rollback(status);
			throw e;
		}

		return result;
	}

	public void endExpireAllRedpackage() throws Exception{
		//取得过期红包列表
		List<Redpackage>  redpackages =  redpackageMapper.selectExpireRedpackageList();
		for(Redpackage redpackage:redpackages){
			endRedpackage(redpackage.getId());
		}

	}

	//查询去编辑红包页面
	public RedPackageOutDTO queryRedpackageForEdit(Long redpackageId) throws Exception{
		RedPackageOutDTO result = null;
		result = redpackageMapper.selectRedpackageForEdit(redpackageId);
		if(result == null){
			throw new ApplicationException("红包没查到！");
		}

		return result;
	}

	//编辑红包
	public int editRedpackage(RedPackageInDTO inDTO) throws Exception{
		int result = 0;

		Redpackage oldRecord = redpackageMapper.selectByPrimaryKey(inDTO.getId());
		//oldRecord.setSettedValue(oldRecord.getSettedValue()==null?0:oldRecord.getSettedValue());
		oldRecord.setTotalCount(oldRecord.getTotalCount()==null?0:oldRecord.getTotalCount());
		Integer addTotalCount = 0;
		Integer freezeAmount = 0;

		Redpackage record = new Redpackage();
		record.setId(inDTO.getId());
		record.setGmtModified(new Date());
		record.setName(inDTO.getName());
		record.setTotalCount(inDTO.getTotalCount());
		record.setAmountPeruser(inDTO.getAmountPeruser());
		if(oldRecord.getValidTimeType() == ActivityEnum.ValidTimeType.FixedTime.getType()) {
			record.setEndGetTime(inDTO.getEndGetTime());
		}
		addTotalCount = record.getTotalCount() - oldRecord.getTotalCount();
		if(oldRecord.getRedpackageType() == RedPackageType.FixedAmount.getType()){//固定金额
			//计算冻结金额
			freezeAmount =  oldRecord.getFaceValue() * addTotalCount;
			record.setSumAmount((oldRecord.getSumAmount()==null?0:oldRecord.getSumAmount()) + freezeAmount);
		}
		redpackageMapper.updateByPrimaryKeySelective(record);

		//追加冻结金额
		if(freezeAmount<=0)
			return -1;

		//增加营销账户冻结金额
		groupAccountService.updateAmount(inDTO.getGroupId(),
				BizEnum.SaleAccountSubjectType.RedPackageCreate,freezeAmount,record.getId(),null,"红包增加数量");

		return result;
	}

	//红包领取(返回领取金额)
	//@Override
	public int insertRedpackageUser(String memberId, String redpackageUserId) throws Exception {

		synchronized(this) {
			RedpackageUser redpackageUser = redpackageUserMapper.selectByPrimaryKey(Long.parseLong(redpackageUserId));
			if (redpackageUser.getGetStatus() != ActivityEnum.RedpackageGetStatus.Received.getType()) {
				throw new ApplicationException(Rescode.FAIL, "红包状态不正确，不能领取！");
			}
			//根据红包有效期的自然日计算
			Date validDate = DateUtil.fomatDate(DateUtil.fomatDate(redpackageUser.getValidTime(), DateUtil.sdfDays), DateUtil.sdfDays);
			Date nowDate = DateUtil.fomatDateToDate(new Date(), DateUtil.sdfDayC);
			if (nowDate.compareTo(validDate) > 0) {
				throw new ApplicationException(Rescode.FAIL, "红包已过有效期，不能领取了！");
			}
			//取得红包信息
			Redpackage redpackage = redpackageMapper.selectByPrimaryKey(redpackageUser.getRedpackageId());
			Integer amount = 0;//红包金额
			if (redpackage.getRedpackageType() == RedPackageType.FixedAmount.getType()) {
				amount = redpackage.getFaceValue();
			} else if (redpackage.getRedpackageType() == RedPackageType.RandomAmount.getType()) {
				//先判断份数是否已经领取完
				amount = CommonFunction.getRandNumberStr(redpackage.getMinValue(), redpackage.getMaxValue());
			}

			redpackage.setSumAmount(redpackage.getSumAmount() == null ? 0 : redpackage.getSumAmount());
			redpackage.setUsedAmount(redpackage.getUsedAmount() == null ? 0 : redpackage.getUsedAmount());
			if(redpackage.getSumAmount() - redpackage.getUsedAmount() == 0) {
				throw new ApplicationException(Rescode.FAIL, "红包预算已经用完，不能领取了！");
			} else if(amount > (redpackage.getSumAmount() - redpackage.getUsedAmount())){
				amount = redpackage.getSumAmount() - redpackage.getUsedAmount();
			}

			//调用充值接口给会员钱包加钱
			//取得会员的虚拟卡号
			Member member = memberMapper.selectByPrimaryKey(Long.parseLong(memberId));
			Group group = groupMapper.selectPayCodeById(member.getGroupId());

			String OrgOrderNum = UtilFun.createOrderNum();

			logger.info("=================红包金额=================="+amount);
			logger.info("=================虚拟卡号=================="+member.getVirtualCard());
			logger.info("=================机构号=================="+group.getPayGroupCode());
			logger.info("=================用户userId=================="+member.getUserId());
			walletService.updateUserLockedAmount(member.getVirtualCard(), group.getPayGroupCode(), member.getUserId(), amount+"", "0", 0,OrgOrderNum);


			//插入线下交易表(红包)
			TradeOffline tradeOffline = new TradeOffline();
			tradeOffline.setGmtCreate(new Date());
			tradeOffline.setGmtModified(new Date());
			tradeOffline.setGroupId(member.getGroupId());
			tradeOffline.setOrderId(OrgOrderNum);
			tradeOffline.setPayOrderid(OrgOrderNum);
			tradeOffline.setPayerId(member.getGroupId());
			tradeOffline.setPayerName(group.getMerchantName());
			tradeOffline.setPayerType((byte) CommonEnum.UserType.BusinessManager.getType());
			tradeOffline.setReceiverId(memberId);
			tradeOffline.setReceiverName(member.getName());
			tradeOffline.setReceiverType((byte) CommonEnum.UserType.User.getType());
			tradeOffline.setTransactionType((byte) BizEnum.TransactionType.RedPackage.getType());
			tradeOffline.setOrderAmount(amount);
			tradeOffline.setRealAmount(amount);
			tradeOffline.setPayType((byte)BizEnum.PaymentType.Wallet.getType());
			tradeOffline.setSubType((byte)BizEnum.PaymentScene.Online.getType());
		//	tradeOffline.setTransOrderNo(payResult.getOrderId());
			tradeOffline.setTransOrderNo(null);
			tradeOffline.setTransactionStatus((byte) BizEnum.TransactionStatus.Success.getType());
			tradeOffline.setIsWallet(Boolean.TRUE);
			tradeOffline.setInNetCompany((byte) BizEnum.InNetCompany.fuqianla.getType());
			tradeOfflineMapper.insertSelective(tradeOffline);

			//更新redpackage_user表
			RedpackageUser updateRedpackageUser = new RedpackageUser();
			updateRedpackageUser.setId(Long.parseLong(redpackageUserId));
			updateRedpackageUser.setGmtModified(new Date());
			updateRedpackageUser.setGetTime(new Date());
			updateRedpackageUser.setGetStatus(ActivityEnum.RedpackageGetStatus.Gotten.getType());
			updateRedpackageUser.setRealAmount(amount);
			redpackageUserMapper.updateByPrimaryKeySelective(updateRedpackageUser);

			//更新redpackage表
			redpackageMapper.updateHaveGetCountByRedpackageUserId(amount, redpackageUser.getRedpackageId());

			//更新营销账户
			groupAccountService.updateAmount(member.getGroupId(), BizEnum.SaleAccountSubjectType.RedPackageGet,
					amount, Long.parseLong(redpackageUserId), null, null);

			return amount;
		}
	}

}
